package adsi.server;

import adsi.domain.*;
import adsi.persistence.*;

import java.util.*;

import org.json.*;

public class MaintenancesLogic {

    private final static MaintenancesLogic instance = new MaintenancesLogic();
    private MaintenanceFactory factory;

    private MaintenancesLogic() {
        factory = MaintenanceFactory.getInstance();
    }

    public static MaintenancesLogic getInstance() {
        return instance;
    }

    private boolean hasValidParameters(String[] keys, JSONObject parameters) throws JSONException {
        StringBuilder message = new StringBuilder();
        Map<String, String> types = new HashMap();
        Map<String, Object> params = new HashMap();

        types.put("id", "int");
        types.put("description", "String");
        types.put("duration", "int");
        types.put("list", "JSONArray");
        types.put("from", "int");
        types.put("to", "int");
        try {
            for (String k : keys) {
                String t = types.get(k);
                params.put(k, null);
                if (t.equals("int")) {
                    params.put(k, parameters.getInt(k));
                } else if (t.equals("String")) {
                    params.put(k, parameters.getString(k));
                } else if (t.equals("JSONArray")) {
                    params.put("description", null);
                    params.put("duration", null);
                    parameters.put("description", "");
                    parameters.put("duration", "");
                    JSONArray jsonList = parameters.getJSONArray(k);
                    String description = (String) jsonList.get(0);
                    params.put("description", description);
                    parameters.put("description", description);
                    int duration = Integer.parseInt((String) jsonList.get(1));
                    params.put("duration", duration);
                    parameters.put("duration", duration);
                }
            }
        } catch (Exception e) {
            System.out.println("Validation error");
            e.printStackTrace();
        }

        if (params.containsKey("id")) {
            Integer ID = (Integer) params.get("id");
            if (ID == null || ID != null && ID < 0) {
                message.append("La ID no debe ser menor a 0.\n");
            }
        }

        if (params.containsKey("description")) {
            String description = (String) params.get("description");
            if (description == null || description != null && description.trim().length() == 0) {
                message.append("La descripción no puede estar vacía.\n");
            }
        }

        if (params.containsKey("duration")) {
            Integer duration = (Integer) params.get("duration");
            if (duration == null || duration != null && duration <= 0) {
                message.append("La duración debe estar en números enteros y ser mayor a cero.\n");
            }
        }

        String[] days = {"from", "to"};
        for (String d : days) {
            Integer duration = (Integer) params.get(d);
            if (duration != null && duration <= 0) {
                message.append("La duración debe estar en números enteros y ser mayor a cero.\n");
            } else if (duration == null) {
                parameters.put(d, -1); //OPTIONAL FIELDS

            }
        }

        parameters.put("ERROR", message.toString());

        return message.toString().length() == 0;
    }

    public String create(JSONObject parameters) throws JSONException {
        String[] keys = {"description", "duration"};

        if (hasValidParameters(keys, parameters)) {
            String description = parameters.getString("description");
            int duration = parameters.getInt("duration");

            Maintenance m = factory.buildMaintenance(-1, description, duration);
            if (!factory.saveMaintenance(m)) {
                parameters.put("ERROR", "No se agregó el registro.");
            }
        }

        return parameters.toString();
    }

    public static void createMany(JSONArray list) throws JSONException {
        for (int i = 0; i < list.length(); i++) {
            instance.create((JSONObject) list.get(i));
        }
    }

    public String edit(JSONObject parameters) throws JSONException {
        String[] keys = {"id", "list"};

        if (hasValidParameters(keys, parameters)) {
            String description = parameters.getString("description");
            int duration = parameters.getInt("duration");
            int id = parameters.getInt("id");

            Maintenance m = factory.buildMaintenance(id, description, duration);
            if (!factory.saveMaintenance(m)) {
                parameters.put("ERROR", "No se modificó el registro.");
            }
        }

        return parameters.toString();
    }

    public String remove(JSONObject parameters) throws JSONException, DataServiceException {
        String[] keys = {"id"};

        if (hasValidParameters(keys, parameters) && !factory.deleteMaintenance(parameters.getInt("id"))) {
            parameters.put("ERROR", "No se modificó el registro.");
        }

        return parameters.toString();
    }

    public String getFormattedSuggestions(JSONObject parameters) throws JSONException {
        String searchWords = parameters.getString("searchWords");
        StringBuilder sb = new StringBuilder();

        List<Maintenance> list = factory.retrieveMaintenancesLike(searchWords);
        list = factory.orderMaintenances(list, "description");
        for (Maintenance m : list) {
            sb.append("<li>" + m.getDescription() + "</li>");
        }

        return "<ul>" + sb.toString() + "</ul>";
    }

    public String search(JSONObject parameters) throws JSONException {
        String searchWords = parameters.getString("postData");
        String order = parameters.getString("order");

        List<Maintenance> list = factory.retrieveMaintenancesLike(searchWords);
        list = factory.orderMaintenances(list, order);

        return render(list);
    }

    public String advancedSearch(JSONObject parameters) throws JSONException {
        String[] keys = {"from", "to"};
        List<Maintenance> list = new ArrayList();

        if (hasValidParameters(keys, parameters)) {
            int from = parameters.getInt("from");
            int to = parameters.getInt("to");
            //String filter = parameters.getString("filter");
            String order = parameters.getString("order");

            list = factory.retrieveMaintenancesInRange(from, to);
            list = factory.orderMaintenances(list, order);

            return render(list);
        } else {
            return parameters.toString();
        }
    }

    public String read(JSONObject parameters) throws JSONException {
        String filter = parameters.getString("filter");
        String order = parameters.getString("order");

        List<Maintenance> list = factory.retrieveMaintenances(filter, order);

        return render(list);
    }

    private String render(List<Maintenance> list) throws JSONException {
        JSONObject jsonResponse = new JSONObject();

        jsonResponse.put("render", true);
        jsonResponse.put("items", list);

        return jsonResponse.toString();
    }
}
